昨天談了 key-value partition,但在實務上,我們可能會為一些具指標性的欄位建立第二、第三個 index,secondary index 的目的不是要識別到單筆資料,而是要透過這個幫助工程師更快速的查詢到特定的值,例如快速找到所有紅色的車款。
許多的 relational 和 document 資料庫都支援 scondary index,既然這麼實用,我們就得研究研究如何在已用 key 切好 partition 的情況下,讓我們的 secondary index 也做 partition ,接下來介紹 2 種主要的方法:document-based partitioning 和 term-based partitioning。
想像一下你有一個賣二手車的網站,每台車都有自己的 unique ID (也是 document ID,我們使用 document 資料庫),你的 partition 策略選擇 key 範圍,例㜶 0~499 為 partition 0,500~999 為 partition 1 以此類推。
你想讓 user 能用顏色和車廠來搜尋二手車,所以你需要為這 2 個 fields 建立 secondary index,爾後你在新增紅色的車款時,資料庫就會自動將 color:red
當做進入點字串來建立 index,建立完成後如下圖:
可以看到這個 index 的方法,每個 partition 都是完全的將 index 分離,每個 partition 都維護自己的 secondary index ,裡頭只列出該 partition 底下的 document id,互不干擾,之後不管你是新增、更新、刪除都只會影響某一個 partition,這就是 document-partition 也被稱為 local index 。
現在我們想查紅色二手車,在這個 index 方法底下,我們一定得查詢 所有 的 partition,這個查詢方法也稱為 scatter/gather ,因為是查所有的 partition,所以這個查詢操作是昂貴的,會傾向增加 P99 response time (Day 3)。
儘管如此,document-partition 還是被廣泛的運用到 MongoDB, Riak, Cassandra, Elasticsearch, SolorCloud 這些資料庫上。
不像前一個 index 方法是存在每個 partition 裡 (local index),接下來這個 index 方法也稱為 global index ,它就只把它存在一個 partition 裡,如下圖:
可以看到我們的紅色二手車 color_red
只出現在 partition 0 裡頭了,partition 1 裡沒有,這個方法會將 color_red
視為完整字串項目來做 partition,所以 partition 0 只存了 a ~ r 字母顏色開頭的車, partition 1 只存了 s ~ z 字母顏色開頭的車,車廠 make:
亦同,這就是 term-partition 。
global (term-partition) index 的好處就是讀取變的有效率了,因為它不用像 document-partition 那樣需要讀所有的 partition,反之缺點就是寫入比較慢和複雜,因為一筆 document 會影響許多的 partition。